/**
 * 功能：16位与32位的启动混合代码
 *
 *创建时间：2022年8月31日
 *作者：李述铜
 *联系邮箱: 527676163@qq.com
 *相关信息：此工程为《从0写x86 Linux操作系统》的前置课程，用于帮助预先建立对32位x86体系结构的理解。整体代码量不到200行（不算注释）
 *课程请见：https://study.163.com/course/introduction.htm?courseId=1212765805&_trace_c_p_k2_=0bdf1e7edda543a8b9a0ad73b5100990
 */
	#include "os.h"

	// 声明本地以下符号是全局的，在其它源文件中可以访问
	.global _start

	// 指定以下的代码生成16位的机器指令，这样才能在启动时的实模式下运行
  	.code16

	// 以下是代码区
 	.text
_start: 
	mov $0, %ax
	mov %ax, %es
	mov %ax, %ds
	mov %ax, %ss
	mov %ax, %fs
	mov %ax, %gs
	mov $_start, %esp     //这里是配置栈空间，可以看到 代码区是0x7c00 +  的内存地址，因为压栈的方式的问题 0x0000~0x7c00 这里为栈空间并且向下 0x7c00 -内存



read_self:
	mov $0x7e00, %bx         //mem address
	mov $0x0080, %dx         //配置读那个硬盘
	//配置读硬盘那个扇区，读多少
	mov $0x0002, %cx         // ch:磁道号，cl起始扇区号
	mov $0x0240, %ax         // ah: 0x42读磁盘命令, al=0x40 64个扇区，多读一些, 32KB					         
						     //配置0x13中断的参数
	int $0x13                //0x13 interupt
	jc read_self
	//================================================================
	//进入保护模式的流程 1关中断 2加载描述符表 3配置cr0
	cli
	lgdt [gdt_desc]
	mov $0x0001, %ax
	lmsw %ax

	jmp $KERNEL_CODE_SEG, $_start_32

	.org 0x01fe   //510  最后两个字节 55 aa
	.byte 0x55, 0xaa   





	.code32
	.text
//在 55aa后  0x7c00 + 512 个字节 = 0x7e00
_start_32:
	//.fill 64*1024, 1, 0x35 //填充pe结构
	mov $KERNEL_DATA_SEG, %eax
	mov %eax, %es
	mov %eax, %ds
	mov %eax, %ss
	mov %eax, %fs
	mov %eax, %gs
	mov $_start, %esp   //config stack

	//===========================cr3 cr0 cr4=====================================
	call page_init
	//打开页表，启动分页机制 线性地址[32] = [10页目录] + [10页表项] +[12偏移 4k]
	mov $pg_dir_table , %eax
	mov %eax, %cr3 

	//p配置 cr4
	mov %cr4, %eax
	orl $(1<<4), %eax
	mov %eax, %cr4

	//配置cr0 打开分页
	mov %cr0, %eax
	orl $(1<<31), %eax
	mov %eax, %cr0

	jmp .

gdt_desc:
	.word (256*8) - 1	 //限长  lgdtr [32]+[16]  寄存器
	.long gdt_table